#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cjson/cJSON.h>
#include "basemodel/jsonrpc/notifications.h"

// 将 jsonrpc_version_t 枚举转换为字符串
const char* jsonrpc_version_to_string(jsonrpc_version_t version) {
    switch (version) {
        case JSONRPC_VERSION_2_0:
            return "2.0";
        default:
            return "unknown";
    }
}

// 将 jsonrpc_notification_t 结构体转换为 cJSON 对象
cJSON* jsonrpc_notification_to_json(const jsonrpc_notification_t* notification) {
    if (!notification) {
        return NULL;
    }
    
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        return NULL;
    }
    
    // 添加 jsonrpc 版本
    cJSON *jsonrpc_item = cJSON_CreateString(jsonrpc_version_to_string(notification->jsonrpc));
    if (!jsonrpc_item) {
        cJSON_Delete(json);
        return NULL;
    }
    cJSON_AddItemToObject(json, "jsonrpc", jsonrpc_item);
    
    // 添加 method
    cJSON *method_item = cJSON_CreateString(notification->method);
    if (!method_item) {
        cJSON_Delete(json);
        return NULL;
    }
    cJSON_AddItemToObject(json, "method", method_item);
    
    // 如果有参数，添加 params
    if (notification->has_params && strlen(notification->params) > 0) {
        // 尝试解析 params 为 JSON 对象或数组
        cJSON *params_json = cJSON_Parse(notification->params);
        if (params_json) {
            cJSON_AddItemToObject(json, "params", params_json);
        } else {
            // 如果解析失败，作为字符串添加
            cJSON *params_item = cJSON_CreateString(notification->params);
            if (params_item) {
                cJSON_AddItemToObject(json, "params", params_item);
            }
        }
    }
    
    return json;
}

// 测试函数：创建并转换 jsonrpc_notification_t
void test_jsonrpc_notification() {
    printf("=== 测试 jsonrpc_notification_t 结构体转 JSON ===\n\n");
    
    // 测试用例 1: 无参数通知
    jsonrpc_notification_t notification1 = {0};
    notification1.jsonrpc = JSONRPC_VERSION_2_0;
    strcpy(notification1.method, "notifications/initialized");
    notification1.has_params = false;
    
    printf("测试用例 1: 无参数通知\n");
    printf("结构体内容:\n");
    printf("  jsonrpc: %d (2.0)\n", notification1.jsonrpc);
    printf("  method: %s\n", notification1.method);
    printf("  has_params: %s\n", notification1.has_params ? "true" : "false");
    
    cJSON *json1 = jsonrpc_notification_to_json(&notification1);
    if (json1) {
        char *json_string1 = cJSON_Print(json1);
        printf("JSON 输出:\n%s\n\n", json_string1);
        free(json_string1);
        cJSON_Delete(json1);
    }
    
    // 测试用例 2: 带简单参数通知
    jsonrpc_notification_t notification2 = {0};
    notification2.jsonrpc = JSONRPC_VERSION_2_0;
    strcpy(notification2.method, "textDocument/didOpen");
    notification2.has_params = true;
    strcpy(notification2.params, "{\"uri\": \"file:///example.txt\", \"languageId\": \"plaintext\"}");
    
    printf("测试用例 2: 带 JSON 对象参数通知\n");
    printf("结构体内容:\n");
    printf("  jsonrpc: %d (2.0)\n", notification2.jsonrpc);
    printf("  method: %s\n", notification2.method);
    printf("  has_params: %s\n", notification2.has_params ? "true" : "false");
    printf("  params: %s\n", notification2.params);
    
    cJSON *json2 = jsonrpc_notification_to_json(&notification2);
    if (json2) {
        char *json_string2 = cJSON_Print(json2);
        printf("JSON 输出:\n%s\n\n", json_string2);
        free(json_string2);
        cJSON_Delete(json2);
    }
    
    // 测试用例 3: 带数组参数通知
    jsonrpc_notification_t notification3 = {0};
    notification3.jsonrpc = JSONRPC_VERSION_2_0;
    strcpy(notification3.method, "workspace/didChangeWatchedFiles");
    notification3.has_params = true;
    strcpy(notification3.params, "{\"changes\": [{\"uri\": \"file:///test1.txt\", \"type\": 1}, {\"uri\": \"file:///test2.txt\", \"type\": 2}]}");
    
    printf("测试用例 3: 带复杂嵌套参数通知\n");
    printf("结构体内容:\n");
    printf("  jsonrpc: %d (2.0)\n", notification3.jsonrpc);
    printf("  method: %s\n", notification3.method);
    printf("  has_params: %s\n", notification3.has_params ? "true" : "false");
    printf("  params: %s\n", notification3.params);
    
    cJSON *json3 = jsonrpc_notification_to_json(&notification3);
    if (json3) {
        char *json_string3 = cJSON_Print(json3);
        printf("JSON 输出:\n%s\n\n", json_string3);
        free(json_string3);
        cJSON_Delete(json3);
    }
    
    // 测试用例 4: 带非法 JSON 参数通知（测试错误处理）
    jsonrpc_notification_t notification4 = {0};
    notification4.jsonrpc = JSONRPC_VERSION_2_0;
    strcpy(notification4.method, "custom/notification");
    notification4.has_params = true;
    strcpy(notification4.params, "这是一个非 JSON 格式的字符串参数");
    
    printf("测试用例 4: 带非 JSON 格式参数通知\n");
    printf("结构体内容:\n");
    printf("  jsonrpc: %d (2.0)\n", notification4.jsonrpc);
    printf("  method: %s\n", notification4.method);
    printf("  has_params: %s\n", notification4.has_params ? "true" : "false");
    printf("  params: %s\n", notification4.params);
    
    cJSON *json4 = jsonrpc_notification_to_json(&notification4);
    if (json4) {
        char *json_string4 = cJSON_Print(json4);
        printf("JSON 输出:\n%s\n\n", json_string4);
        free(json_string4);
        cJSON_Delete(json4);
    }
}

// 反向测试：从 JSON 字符串解析为结构体
int json_to_jsonrpc_notification(const char* json_string, jsonrpc_notification_t* notification) {
    if (!json_string || !notification) {
        return -1;
    }
    
    cJSON *json = cJSON_Parse(json_string);
    if (!json) {
        return -1;
    }
    
    // 初始化结构体
    memset(notification, 0, sizeof(jsonrpc_notification_t));
    
    // 解析 jsonrpc 版本
    cJSON *jsonrpc_item = cJSON_GetObjectItem(json, "jsonrpc");
    if (cJSON_IsString(jsonrpc_item)) {
        if (strcmp(jsonrpc_item->valuestring, "2.0") == 0) {
            notification->jsonrpc = JSONRPC_VERSION_2_0;
        }
    }
    
    // 解析 method
    cJSON *method_item = cJSON_GetObjectItem(json, "method");
    if (cJSON_IsString(method_item)) {
        strncpy(notification->method, method_item->valuestring, sizeof(notification->method) - 1);
    }
    
    // 解析 params
    cJSON *params_item = cJSON_GetObjectItem(json, "params");
    if (params_item) {
        notification->has_params = true;
        char *params_string = cJSON_Print(params_item);
        if (params_string) {
            strncpy(notification->params, params_string, sizeof(notification->params) - 1);
            free(params_string);
        }
    } else {
        notification->has_params = false;
    }
    
    cJSON_Delete(json);
    return 0;
}

void test_json_to_struct() {
    printf("=== 测试 JSON 字符串转 jsonrpc_notification_t 结构体 ===\n\n");
    
    const char* test_json = "{\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didChange\",\"params\":{\"textDocument\":{\"uri\":\"file:///example.c\",\"version\":2},\"contentChanges\":[{\"text\":\"Hello World\"}]}}";
    
    printf("输入 JSON 字符串:\n%s\n\n", test_json);
    
    jsonrpc_notification_t notification = {0};
    int result = json_to_jsonrpc_notification(test_json, &notification);
    
    if (result == 0) {
        printf("解析成功！结构体内容:\n");
        printf("  jsonrpc: %d (2.0)\n", notification.jsonrpc);
        printf("  method: %s\n", notification.method);
        printf("  has_params: %s\n", notification.has_params ? "true" : "false");
        printf("  params: %s\n", notification.params);
    } else {
        printf("解析失败！\n");
    }
    printf("\n");
}

int main() {
    printf("cJSON 版本: %s\n", cJSON_Version());
    printf("开始测试 jsonrpc_notification_t 结构体与 JSON 的转换\n");
    printf("========================================================\n\n");
    
    // 测试结构体转 JSON
    test_jsonrpc_notification();
    
    // 测试 JSON 转结构体
    test_json_to_struct();
    
    printf("所有测试完成！\n");
    return 0;
}
